/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package persistence;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Random;
import model.BioscoopAdministratieSysteem;
import model.Complex;
import model.Film;
import model.FilmMaatschappij;
import model.Functie;
import model.Klant;
import model.Oscar;
import model.OscarUitreiking;
import model.Persoon;
import model.Ticket;
import model.Verkoop;
import model.VerkoopPunt;
import model.Voorstelling;
import model.Zaal;
import model.ZaalZone;
import model.Zetel;
import model.Zone;

/**
 *
 * @author Matthy & Jelle
 */
public class Installer {

  public static void install() {
    int i, j;
    Random generator = new Random();
    String characters = "abcdefghijklmnopqrstuvwxyz0123456789 ";
    BioscoopAdministratieSysteemService bass = new BioscoopAdministratieSysteemService();
    if (bass.getList().size() > 0) {
      return;
    }
    BioscoopAdministratieSysteem bas = new BioscoopAdministratieSysteem();
    bass.save(bas);

    List<Zone> zones = new ArrayList<Zone>();
    List<FilmMaatschappij> filmmaatschappijen = new ArrayList<FilmMaatschappij>();
    List<Film> films = new ArrayList<Film>();
    List<Complex> complexen = new ArrayList<Complex>();
    List<Zaal> zalen = new ArrayList<Zaal>();
    List<Klant> klanten = new ArrayList<Klant>();
    List<VerkoopPunt> verkoopPunten = new ArrayList<VerkoopPunt>();

    String[] genres = {
      "Adventure",
      "Action",
      "Romance",
      "Science-Fiction",
      "Comedy",
      "Drama",
      "Fantasy",
      "Family",
      "Crime",
      "War",
      "Mystery",
      "Documentary",
      "Thriller",
      "Horror",
      "Western"
    };

    VerkoopPuntService verkoopPuntService = new VerkoopPuntService();
    FilmMaatschappijService filmMaatschappijService = new FilmMaatschappijService();
    FilmService fimService = new FilmService();
    ZoneService zoneService = new ZoneService();
    ZaalZoneService zaalZoneService = new ZaalZoneService();
    ComplexService complexService = new ComplexService();
    ZetelService zetelService = new ZetelService();
    ZaalService zaalService = new ZaalService();
    KlantService klantService = new KlantService();
    FunctieService functieService = new FunctieService();
    PersoonService persoonService = new PersoonService();
    OscarService oscarService = new OscarService();
    OscarUitreikingService oscarUitreikingService = new OscarUitreikingService();
    TicketService ticketService = new TicketService();

    // Voeg zones toe.
    Zone normaal = new Zone();
    normaal.setPrijs(8);
    normaal.setType("normaal");

    zoneService.save(normaal);
    zones.add(normaal);

    Zone loveseat = new Zone();
    loveseat.setPrijs(10);
    loveseat.setType("loveseat");

    zoneService.save(loveseat);
    zones.add(loveseat);

    Zone rolstoel = new Zone();
    rolstoel.setPrijs(9);
    rolstoel.setType("rolstoel");

    zoneService.save(rolstoel);
    zones.add(rolstoel);

    // Genereer verkoop punten.
    for (i = 0; i < 25; i++) {
      VerkoopPunt verkoopPunt = new VerkoopPunt();
      verkoopPunt.setAdministratiesysteem(bas);
      verkoopPunt.setLocatie(Installer.generateString(generator, characters, 20));
      verkoopPuntService.save(verkoopPunt);
      verkoopPunten.add(verkoopPunt);
    }

    // Genereer klanten
    for (i = 0; i < 10000; i++) {
      Klant klant = new Klant();
      klant.setAdres(Installer.generateString(generator, characters, 20));
      klant.setGsm(Installer.generateString(generator, characters, 10));
      klant.setNaam(Installer.generateString(generator, characters, 15));
      klant.setVoornaam(Installer.generateString(generator, characters, 10));
      klantService.save(klant);
      klanten.add(klant);
    }

    // Genereer complexen.
    for (i = 0; i < 4; i++) {
      Complex complex = new Complex();
      complex.setAdministratiesysteem(bas);
      complex.setLocatie(Installer.generateString(generator, characters, 20));
      complexService.save(complex);
      complexen.add(complex);
    }

    // Genereer filmmaatschappijen.
    for (i = 0; i < 20; i++) {
      FilmMaatschappij filmMaatschappij = new FilmMaatschappij();
      filmMaatschappij.setNaam(Installer.generateString(generator, characters, 10));
      filmMaatschappijService.save(filmMaatschappij);
      filmmaatschappijen.add(filmMaatschappij);
    }

    // Genereer films 40 films voor 6 weken over 10 jaar verspreid = 86 periodes van 6 weken.
    for (i = 0; i < (40 * 86); i++) {
      Film film = new Film();
      film.setFilmMaatschappij(filmmaatschappijen.get(generator.nextInt(filmmaatschappijen.size())));
      film.setGenre(genres[generator.nextInt(genres.length)]);
      film.setKinderenToegelaten(i % 2 == 0);
      film.setKorteInhoud(Installer.generateString(generator, characters, 30));
      film.setTitel(Installer.generateString(generator, characters, 20));
      film.setLand(Installer.generateString(generator, characters, 15));
      film.setSpeelDuur(generator.nextInt(190));
      fimService.save(film);
      films.add(film);
      for (j = 0; j < 5; j++) {
        Functie functie = new Functie();
        functie.setFilm(film);
        functie.setPersonageNaam(Installer.generateString(generator, characters, 20));
        functie.setNaam(Installer.generateString(generator, characters, 15));
        Persoon persoon = new Persoon();
        persoon.setGeboorteDatum(Installer.generateDate(generator, generator.nextInt(365), 1970 + generator.nextInt(42)));
        persoon.setGeslacht(generator.nextBoolean() ? "M" : "V");
        persoon.setNaam(Installer.generateString(generator, characters, 15));
        persoon.setVoornaam(Installer.generateString(generator, characters, 10));
        functie.setPersoon(persoon);
        persoonService.save(persoon);
        functieService.save(functie);
      }
    }

    // Genereer zalen met zaalzones en zetels in deze zones.
    for (i = 0; i < 40; i++) {
      Zaal zaal = new Zaal();
      zaal.setComplex(complexen.get(generator.nextInt(complexen.size())));
      zaal.setNr(i + 1);
      zaalService.save(zaal);
      List<ZaalZone> zaalzones = new ArrayList<ZaalZone>();
      for (j = 0; j < zones.size(); j++) {
        if (generator.nextBoolean() || j == 0) {
          ZaalZone zaalZone = new ZaalZone();
          zaalZone.setZaal(zaal);
          zaalZone.setZone(zones.get(j));
          zaalZoneService.save(zaalZone);
          zaalzones.add(zaalZone);
        }
      }
      for (int k = 0; k < 100; k++) {
        Zetel zetel = new Zetel();
        zetel.setNr(k);
        zetel.setZaalzone(zaalzones.get(100 % zaalzones.size()));
        zetelService.save(zetel);
      }
      zalen.add(zaal);
    }

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(new Date());
    Integer currentyear = calendar.get(Calendar.YEAR);
    Integer currentday = calendar.get(Calendar.DAY_OF_YEAR);
    Integer minDay = currentday - 14;
    Integer maxDay = currentday + 7;
    Integer year;


    // Genereer voorstellingen voor de voorbije 10 jaar.
    for (int k = 0; k < 10; k++) {
      year = currentyear - k;
      for (i = 0; i < 365; i++) {
        generator = new Random();
        for (Zaal z : zalen) {
          for (j = 0; j < 3; j++) {
            Boolean saved;
            Voorstelling voorstelling;
            do {
              Date date = Installer.generateTime(i + 1, year, j);
              voorstelling = new Voorstelling();
              voorstelling.setFilm(films.get(generator.nextInt(films.size())));
              voorstelling.setOndertiteling(generator.nextBoolean() ? "NL" : "FR");
              voorstelling.setTaal(generator.nextBoolean() ? "EN" : "NL");
              voorstelling.setTijdstip(date);
              voorstelling.setType(generator.nextBoolean() ? "2D" : "3D");
              voorstelling.setZaal(z);
              VoorstellingService voorstellingService = new VoorstellingService();
              saved = voorstellingService.save(voorstelling);
            } while (!saved);
            // genereer verkopen en tickets
            // verkopen van de voorbije 2 weken en de komende week
            // Als we verkopen voor alle jaren voor alle complexen voor elke dag willen doen hebben we
            // 21 000 000 (4 complexen x 10 zalen x 50 zetels (zalen voor de helft uitverkocht) x 365 dagen x 3 voorstellingen per dag x 10 jaar) tickets => dit duurt te lang
            if (year.equals(currentyear) && i > minDay.intValue() && i < maxDay.intValue()) {
              for (int l = 0; l < 25; l++) {
                Verkoop verkoop = new Verkoop();
                verkoop.setDatum(voorstelling.getTijdstip());
                verkoop.setKlant(klanten.get(generator.nextInt(klanten.size())));
                verkoop.setVerkooppunt(verkoopPunten.get(generator.nextInt(verkoopPunten.size())));
                for (int m = 0; m < 2; m++) {
                  Ticket ticket = new Ticket();
                  ticket.setBarcode(ticketService.generateBarcode());
                  Boolean studentenKorting = generator.nextBoolean();
                  ticket.setStudentenkorting(studentenKorting);
                  ticket.setVoorstelling(voorstelling);
                  ticket.setVerkoop(verkoop);
                  List<Zetel> vrijeZetels = zetelService.getVrijeZetels(voorstelling);
                  ticket.setZetel(vrijeZetels.get(generator.nextInt(vrijeZetels.size())));
                  Integer totaalprijs = ticket.getZetel().getZaalzone().getZone().getPrijs();
                  if (studentenKorting) {
                    totaalprijs -= 2;
                  }
                  if (voorstelling.getType().equals("3D")) {
                    totaalprijs += 3;
                  }
                  ticket.setTotaalprijs(totaalprijs);
                  ticketService.save(ticket);
                }
              }
            }
          }
        }
      }
    }
    // Genereer oscars & uitreikingen (10 oscars per jaar over 10 jaar verspreid)
    for (i = 0; i < 10; i++) {
      Oscar oscar = new Oscar();
      oscar.setNaam(Installer.generateString(generator, characters, 10));
      oscarService.save(oscar);
      for (j = 0; j < 10; j++) {
        Integer jaar = 2002 + j;
        for (int k = 0; k < 15; k++) {
          Film film = films.get(generator.nextInt(films.size()));
          OscarUitreiking oscarUitreiking = new OscarUitreiking();
          oscarUitreiking.setDatum(Installer.generateDate(generator, generator.nextInt(365), jaar));
          oscarUitreiking.setFilm(film);
          oscarUitreiking.setOscar(oscar);
          oscarUitreikingService.save(oscarUitreiking);
        }
      }
    }
  }

  public static String generateString(Random rng, String characters, int length) {
    char[] text = new char[length];
    for (int i = 0; i < length; i++) {
      text[i] = characters.charAt(rng.nextInt(characters.length()));
    }
    return new String(text);
  }

  public static Date generateDate(Random rng, Integer day, Integer year) {
    Calendar calendar = Calendar.getInstance();
    if (day > 365) {
      year += 1;
      day = day - 365;
    }
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.DAY_OF_YEAR, day);
    calendar.set(Calendar.HOUR_OF_DAY, 10 + rng.nextInt(15));
    return calendar.getTime();
  }

  public static Date generateTime(Integer day, Integer year, Integer period) {
    Calendar calendar = Calendar.getInstance();
    if (day > 365) {
      year += 1;
      day = day - 365;
    }
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.DAY_OF_YEAR, day);
    calendar.set(Calendar.HOUR_OF_DAY, 10 + 4 * period);
    return calendar.getTime();
  }
}
